<?php

declare(strict_types=1);

namespace app\libs\token;

/**
 * Token类
 */
abstract class Token
{
	protected $config = [
		'name' => '', // Token实例的名称，同一类token应该相同，一般用模型名
		'expire_time' => 7200, // 超时时长，秒，null表示不限
	];

	public function __construct($config = [])
	{
		$this->config = array_merge($this->config, $config);
	}

	public function getConfig()
	{
		return $this->config;
	}

	/** 生成唯一token字符串 */
	public function generateToken()
	{
		$token = md5(uniqid(md5((string)microtime(true)), true));
		while ($this->has($token)) {
			$token = md5(uniqid(md5((string)microtime(true)), true));
		}
		return $token;
	}

	/**
	 * 通过Token获取数据的唯一标识
	 * @param string $token token
	 * @return null|string|int 若不存在返回null
	 */
	abstract function get(string $token);

	/**
	 * 通过数据的唯一标识获取token
	 * @param string|int $key 数据的唯一标识
	 * @param boolean $all 是否获取所有（默认单个）
	 * @return string|array
	 */
	abstract function token($key, $all = false);

	/**
	 * 生成Token
	 * @param string|int $key 数据的唯一标识
	 * @param int|null $expireTime 有效时长（如果为null则自动采用$config中的expire_time）
	 * @param string|null $token 指定token，可以通过这个方式强制更新这个token
	 * @return boolean
	 */
	abstract function create($key, int $expireTime = null, string $token = null);

	/**
	 * token是否存在
	 * @param string $token
	 * @return boolean
	 */
	abstract function has(string $token);

	/**
	 * 删除token
	 * @param string $token
	 * @return boolean
	 */
	abstract function delete(string $token);

	/**
	 * 清空token
	 * @param null|string|int $key 数据的唯一标识（若传入null则清空所有）
	 * @return mixed
	 */
	abstract function clear($key = null);

	/**
	 * 获取/设置token的有效时长
	 * @param string $token
	 * @param null|int $expireTime 有效时长（秒）
	 * @return mixed 获取时如果token存在则返回有效时长，否则返回false；设置时返回设置结果
	 */
	abstract function ttl(string $token, $expireTime = null);
}
